fix(mcp): fix resource leak and stale-header bug in MCP client - #890
fix(mcp): fix resource leak and stale-header bug in MCP client#890h4sht wants to merge 1 commit into
Conversation
- Fix hashConfig to include headers for HTTP/SSE configs, preventing stale auth tokens when two MCP servers differ only by headers. - Add closeMCPClient() export to clean up client connections and cached tool listings, fixing the memory/connection leak where runningClients and listToolsCache grew without bound. - Integrate automatic cleanup in SDK: when an MCP tool call fails, the dead client is evicted so the next call reconnects with a fresh transport instead of reusing the broken connection.
|
Thanks — this addresses two important reliability issues for projects using authenticated HTTP/SSE MCP servers. Including Would it be possible to add regression tests for:
The documented limitation around silently dead transports also makes sense. A small follow-up for a liveness check or TTL-based eviction would improve long-running sessions further. Overall, this looks like a valuable fix for real user projects. |
|
Good catch on both bugs. The The
Overall this is a small, well-targeted fix addressing a real caching bug with a clear root cause. Recommend porting after maintainers verify test coverage or add a couple of unit tests. Nice first PR. |
Summary
Fixes two related bugs in the MCP client module that cause resource leaks and stale connections:
1. Memory/Connection Leak — No Client Cleanup
The `runningClients` map and `listToolsCache` in `common/src/mcp/client.ts` grew without bound. Once an MCP client was connected, it was never removed from the registry, even after the transport died or the session ended. In long-running sessions with MCP tools, this accumulates stale connections and never releases resources.
Fix: Added `closeMCPClient(clientId)` — closes the underlying transport (stdio process or HTTP/SSE connection) and removes entries from both `runningClients` and `listToolsCache`.
2. Stale Headers in Config Hash
`hashConfig()` did not include `config.headers` when computing the cache key for HTTP and SSE transports. Two MCP server configs with different auth tokens but the same URL were treated as the same client, returning a cached client with stale credentials.
Fix: Added `headers: config.headers` to the hash for both `http` and `sse` config types.
3. Automatic Cleanup on Tool Call Failure
When an MCP tool call failed (broken connection, dead stdio process), the dead client remained in the cache. Subsequent calls would reuse the same broken connection and fail with the same error.
Fix: In `sdk/src/run.ts`, the MCP tool call catch block now calls `closeMCPClient()` to evict the dead client so the next call reconnects with a fresh transport.
Files changed
Known limitations